package com.nightwalkbuddy.ui;

import com.nightwalkbuddy.dao.IPathDAO;
import com.nightwalkbuddy.dao.PathProviderLive;
import com.nightwalkbuddy.dto.MapPair;
import com.nightwalkbuddy.service.IPathService;
import com.nightwalkbuddy.service.PathServiceLive;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.sqlite.SQLiteException;
import android.telephony.SmsManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;

/**
 * View menu where the main activities are originated.
 * 
 */
public class MenuActivity extends Activity {

	private MediaPlayer mp;
	private static final String CLASSNAME = "MenuActivity.java";
	private static final String MY_GPS = " and my GPS location: ";
	private static final String STOP_WALK = "Stop Walk";
	private static final String ALARM_ACTIVATED = "Alarm has been activated";
	private int spinnerPosition;
	private int alarm_selected;
	// for SMS message
	private static final String SMS_NOT_DELIVERED = "SMS not delivered";
	private static final String SMS_DELIVERED = "SMS delivered";
	private static final String RADIO_OFF = "Radio off";
	private static final String NULL_PDU = "Null PDU";
	private static final String NO_SERVICE = "No service";
	private static final String GENERIC_FAILURE = "Generic failure";
	private static final String SMS_SENT = "SMS sent";
	private static final String SENT = "TEXT_SENT";
	private static final String DELIVERED = "TEXT_DELIVERED";

	// for setup GPS update interval
	protected static final int GPS_INTERVAL = 1;
	private double latLoc;
	private double longLoc;
	private LocationManager locationManager;
	private LocationListener locListener;
	private Button btn_startWalk;
	private IPathService aPathService = new PathServiceLive();
	private IPathDAO aPathProvider = new PathProviderLive(this);
	private Button btn_Emergency;
	private Button btn_stopWalk;
	private Spinner spnLocations;
	protected Double destLongLoc;
	protected Double destLatLoc;
	private String aMessage = "";
	private String aPhoneNr = "";
	private String aUserName = "";
	private MapPair<Double, Double> startingPoint;

	// SMS broadcast
	private BroadcastReceiver brSent = new BroadcastReceiver() {

		@Override
		public void onReceive(Context arg0, Intent arg1) {
			switch (getResultCode()) {
			case Activity.RESULT_OK:
				popup(SMS_SENT);
				break;
			case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
				popup(GENERIC_FAILURE);
				break;
			case SmsManager.RESULT_ERROR_NO_SERVICE:
				popup(NO_SERVICE);
				break;
			case SmsManager.RESULT_ERROR_NULL_PDU:
				popup(NULL_PDU);
				break;
			case SmsManager.RESULT_ERROR_RADIO_OFF:
				popup(RADIO_OFF);
				break;
			}
		}

	};
	private BroadcastReceiver brDelivered = new BroadcastReceiver() {
		@Override
		public void onReceive(Context arg0, Intent arg1) {
			switch (getResultCode()) {
			case Activity.RESULT_OK:
				popup(SMS_DELIVERED);
				break;
			case Activity.RESULT_CANCELED:
				popup(SMS_NOT_DELIVERED);
				break;
			}
		}
	};

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_menu);
		initComponents();
		Bundle bundle = new Bundle();
		Intent sender = getIntent();
		bundle = sender.getExtras();

		// prevent the emergency button losing lat/long info when coming back
		// from SettingActivity
		if (bundle.getString("sender").equalsIgnoreCase(
				getString(R.string.title_activity_settings))) {
			latLoc = Double.parseDouble(bundle.getString("lat"));
			longLoc = Double.parseDouble(bundle.getString("long"));
		}

		spinnerPosition = bundle.getInt("spinnerPosition");
		alarm_selected = bundle.getInt("alarm_selected");
		aMessage = bundle.getString("aMessage");
		aPhoneNr = bundle.getString("aPhoneNr");
		aUserName = bundle.getString("aUserName");

		// popup("success: " + aMessage + " " + aPhoneNr);
		registerReceiver(brSent, new IntentFilter(SENT));
		registerReceiver(brDelivered, new IntentFilter(DELIVERED));

	}

	/**
	 * during onPause unregister the receivers
	 */
	protected void onPause() {
		super.onPause();
		unregisterReceiver(brSent);
		unregisterReceiver(brDelivered);
	}

	/**
	 * during onResume register the receivers
	 */
	protected void onResume() {
		super.onResume();
		registerReceiver(brSent, new IntentFilter(SENT));
		registerReceiver(brDelivered, new IntentFilter(DELIVERED));

	}

	/**
	 * Get's Latitude of current Location
	 * 
	 * @return latLoc
	 */
	public double getLat() {
		return latLoc;
	}

	/**
	 * Get's Longitude of current Location
	 * 
	 * @return LongLoc
	 */
	public double getLong() {
		return longLoc;
	}

	/**
	 * update current GPS location service
	 */
	private void updateGPS() {
		if (locListener != null && locationManager != null) {
			locationManager.requestLocationUpdates(
					LocationManager.GPS_PROVIDER, GPS_INTERVAL * 1000, 0,
					locListener);
		}
	}

	/**
	 * stop current GPS location service
	 */
	protected void destroyGPS() {
		if (locListener != null && locationManager != null) {
			locationManager.removeUpdates(locListener);
		}
	}

	/**
	 * start locationListenter to track GPS location from service provider
	 */
	private void startLocListener() {
		locListener = new LocationListener() {
			int cnt = 1;

			@Override
			public void onLocationChanged(Location arg0) {
				latLoc = arg0.getLatitude();
				longLoc = arg0.getLongitude();
				try {
					aPathService.pointToPath(latLoc, longLoc);
				} catch (NullPointerException e) {
					e.printStackTrace();
					Log.e(CLASSNAME, e.toString());
				} catch (Exception e) {
					e.printStackTrace();
					Log.e(CLASSNAME, e.toString());
				}
				if (cnt > 1) {
					try {
						popup(aPathService.printPathPoints());
						aPathService.isOnPath();
					} catch (NullPointerException e) {
						e.printStackTrace();
						Log.e(CLASSNAME, e.toString());
					} catch (Exception e) {
						e.printStackTrace();
						Log.e(CLASSNAME, e.toString());
					}
				}

				// TODO: for sprint#3 testing, remove later
				try {
					popup(aPathService.getPathInProgress());
				} catch (NullPointerException e) {
					e.printStackTrace();
					Log.e(CLASSNAME, e.toString());
				} catch (Exception e) {
					e.printStackTrace();
					Log.e(CLASSNAME, e.toString());
				}
				cnt++;
			}

			@Override
			public void onProviderDisabled(String provider) {
				destroyGPS();
			}

			@Override
			public void onProviderEnabled(String provider) {
				updateGPS();
			}

			@Override
			public void onStatusChanged(String provider, int status,
					Bundle extras) {
				switch (status) {
				case LocationProvider.OUT_OF_SERVICE:
					Log.v(getString(R.string.app_name),
							getString(R.string.out_of_service));
					popup(getString(R.string.out_of_service));
					break;
				case LocationProvider.TEMPORARILY_UNAVAILABLE:
					Log.v(getString(R.string.app_name),
							getString(R.string.temporary_unavailable));
					popup(getString(R.string.temporary_unavailable));
					break;
				case LocationProvider.AVAILABLE:
					Log.v(getString(R.string.app_name),
							getString(R.string.available));
					popup(getString(R.string.available));
					break;
				}
			}
		};
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		getMenuInflater().inflate(R.menu.activity_menu, menu);
		return true;
	}

	/**
	 * Options menu selection
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case R.id.menu_logout:
			menuLogout();
			return (true);
		case R.id.menu_settings:
			menuSettings();
			return (true);
		default:
			return (super.onOptionsItemSelected(item));
		}
	}

	/**
	 * menu logout click
	 */
	private void menuLogout() {
		popup(getString(R.string.goodbye_msg));
		destroyGPS();
		startActivity(new Intent(MenuActivity.this, LoginActivity.class));
		finish();
	}

	/**
	 * if mediaplayer is active stop it.
	 */
	private void checkPlayer() {
		if (mp != null) {
			mp.stop();
		}
	}

	/**
	 * How to handle menu settings click
	 */
	private void menuSettings() {
		Intent intent = (new Intent(this, SettingsActivity.class));
		intent.putExtra(getString(R.string.app_name), true);
		checkPlayer();
		intent.putExtra("spinnerPosition", spinnerPosition);
		intent.putExtra("alarm_selected", this.alarm_selected);
		intent.putExtra("aUserName", this.aUserName);
		intent.putExtra("aMessage", this.aMessage);
		intent.putExtra("aPhoneNr", this.aPhoneNr);

		// passing lat/long info to emergency button on SettingActivity
		intent.putExtra("lat", String.valueOf(latLoc));
		intent.putExtra("long", String.valueOf(longLoc));

		startActivity(intent);
	}

	/**
	 * initialize the view components The logout button has Toast message prior
	 * to logging out the user
	 */
	protected void initComponents() {

		btn_startWalk = (Button) findViewById(R.id.btn_newWalk);
		btn_Emergency = (Button) findViewById(R.id.btn_Emergency);
		spnLocations = (Spinner) findViewById(R.id.spinner_Locations);
		btn_stopWalk = (Button) findViewById(R.id.btnStop);

		/**
		 * button to start alarm that works like a panic button It also sends
		 * SMS text message to emergency contact for help
		 */
		btn_Emergency.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {

				popup(ALARM_ACTIVATED);
				String emMsg = aMessage + MY_GPS + latLoc + ", " + longLoc;

				checkPlayer();

				// create MediaPlayer instance
				mp = MediaPlayer.create(getBaseContext(), alarm_selected);
				// play MediaPlayer
				mp.start();

				// Send text message
				sendSMS(aPhoneNr, emMsg);
			}
		});

		// button to stop tracking user path and save current path to SQLite db
		btn_stopWalk.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				popup(STOP_WALK);
				try {
					aPathProvider.save(aUserName,
							aPathService.getCompletePath());
				} catch (NullPointerException e) {
					e.printStackTrace();
					Log.e(CLASSNAME, e.toString());
				} catch (SQLiteException e) {
					e.printStackTrace();
					Log.e(CLASSNAME, e.toString());
				} catch (Exception e) {
					e.printStackTrace();
					Log.e(CLASSNAME, e.toString());
				}
			}
		});

		btn_startWalk.setOnClickListener(new View.OnClickListener() {

			// retrieve destination lat/long data and setup GPS update
			@Override
			public void onClick(View v) {
				int selectedID = (int) spnLocations.getSelectedItemId();
				MapPair<Double, Double> selectedLocation;
				locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
				popup(getString(R.string.btn_newWalk));
				startLocListener();
				updateGPS();
				if (startingPoint == null) {
					startingPoint = new MapPair<Double, Double>(latLoc, longLoc);
				}

				if (selectedID != 0) {
					selectedLocation = aPathProvider
							.getUCLocation(selectedID - 1);
					popup("UC: " + selectedLocation.getFirst() + " "
							+ selectedLocation.getSecond());
					destLatLoc = selectedLocation.getFirst();
					destLongLoc = selectedLocation.getSecond();
					aPathService
							.setDestination(startingPoint, selectedLocation);
				}
			}
		});
	}

	// method to return to LoginActivity view when logout button is clicked
	protected void getView(View view) {
		Intent intent = new Intent(this, LoginActivity.class);
		intent.putExtra(getString(R.string.app_name), true);
		checkPlayer();
		startActivity(intent);
	}

	// method to pop up Toast message
	protected void popup(String message) {
		Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
	}

	/**
	 * send emergency text message to emergency contact
	 * 
	 * @param phoneNumber
	 *            emergency contact phone number
	 * @param message
	 *            emergency text message
	 */
	private void sendSMS(String phoneNumber, String message) {
		PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent(
				SENT), 0);
		PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,
				new Intent(DELIVERED), 0);

		SmsManager sms = SmsManager.getDefault();
		sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);
	}

}
